home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk1 / files / files.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  14KB  |  669 lines

  1.  
  2. /*
  3.  *  FILES.C
  4.  *
  5.  *  File Manager!
  6.  *
  7.  *  (c)Copyright 1987 Matthew Dillon, All Rights Reserved.
  8.  */
  9.  
  10. #include "files.h"
  11.  
  12. typedef struct FileLock LOCK;
  13.  
  14. extern LOCK *Lock();
  15. extern LOCK *ParentDir(), *CurrentDir();
  16. extern void *malloc();
  17. extern void addentry();
  18.  
  19. RECORD *Rbase;        /*  All entries          */
  20. RECORD *DisplayTop;    /*  Entry at the display top */
  21. RECORD *Highlighted;    /*  Highlighted entry         */
  22. short  MaxNameLen;
  23. long   NumEntries;
  24. long   NumSelected;
  25. long   NumTop;
  26. long   NewNumTop;
  27. FIB    *Fib;
  28. short  Modified;
  29.  
  30. short  Xs, Xe, Ys, Ye, Rows, Cols;
  31.  
  32. char Title[80];
  33.  
  34. redisplay(newtop)
  35. {
  36.     short i;
  37.     short noscroll = 0;
  38.     uword percent, fill;
  39.     RECORD *rec;
  40.  
  41.     bigboxbounds(&Xs,&Xe,&Ys,&Ye);
  42.     Rows = (Ye-Ys)/Rp->TxHeight;
  43.     Cols = (Xe-Xs)/Rp->TxWidth;
  44.  
  45.     if (newtop) {
  46.     long delta = NumTop - NewNumTop;
  47.     if (delta < 0)
  48.         delta = -delta;
  49.     if (delta >= Rows)
  50.         noscroll = 1;
  51.     }
  52.     while (DisplayTop && !(DisplayTop->flags & R_SELECTED))
  53.     DisplayTop = DisplayTop->next;
  54.     if (newtop) {
  55.     while (NewNumTop != NumTop && DisplayTop) {
  56.         if (NewNumTop < NumTop) {
  57.         do {
  58.             DisplayTop = DisplayTop->prev;
  59.         } while (DisplayTop && !(DisplayTop->flags & R_SELECTED));
  60.         --NumTop;
  61.         if (DisplayTop && !noscroll) {
  62.             ScrollRaster(Rp, 0, -Rp->TxHeight, Xs, Ys, Xe-1, Ye-1);
  63.             displayat(DisplayTop, 0);
  64.         }
  65.         } else {
  66.         do {
  67.             DisplayTop = DisplayTop->next;
  68.         } while (DisplayTop && !(DisplayTop->flags & R_SELECTED));
  69.         ++NumTop;
  70.         if (DisplayTop && !noscroll) {
  71.             ScrollRaster(Rp, 0, Rp->TxHeight, Xs, Ys, Xe-1, Ye-1);
  72.             displayrow(Rows-1);
  73.         }
  74.         }
  75.     }
  76.     if (DisplayTop && !noscroll)
  77.         return(0);
  78.     }
  79.     sprintf(Title, "%ld/%ld", NumSelected, NumEntries);
  80.     title(Title);
  81.     if (DisplayTop == NULL) {
  82.     DisplayTop = Rbase;
  83.     NumTop = 0;
  84.     }
  85.     if (!newtop) {
  86.     percent = fill = 0xFFFF;
  87.     if (NumSelected) {
  88.         if (NumTop+(Rows>>1) > NumSelected)
  89.         percent = 0xFFFF;
  90.         else
  91.         percent = (NumTop + (Rows>>1)) * 0xFFFF / NumSelected;
  92.         fill = Rows * 0xFFFF / NumSelected;
  93.         if (Rows > NumSelected)
  94.         fill = 0xFFFF;
  95.     }
  96.     setslider(percent, fill);
  97.     }
  98.     SetAPen(Rp, 0);
  99.     RectFill(Rp, Xs, Ys, Xe-1, Ye-1);
  100.     SetAPen(Rp, 1);
  101.     for (rec = DisplayTop, i = 0; rec && i < Rows; rec = rec->next) {
  102.     if (!(rec->flags & R_SELECTED))
  103.         continue;
  104.     displayat(rec, i);
  105.     ++i;
  106.     }
  107. }
  108.  
  109. redisplayone(rec)
  110. RECORD *rec;
  111. {
  112.     RECORD *nrec;
  113.     short i;
  114.  
  115.     for (i = 0, nrec = DisplayTop; nrec && i < Rows; nrec = nrec->next) {
  116.     if (!(nrec->flags & R_SELECTED))
  117.         continue;
  118.     if (nrec == rec)
  119.         break;
  120.     ++i;
  121.     }
  122.     if (i < Rows && nrec == rec) {
  123.     SetAPen(Rp, 0);
  124.     RectFill(Rp, Xs, Ys + (Rp->TxHeight*i), Xe-1, Ys + (Rp->TxHeight*i) + Rp->TxHeight - 1);
  125.     SetAPen(Rp, 1);
  126.     displayat(rec, i);
  127.     }
  128. }
  129.  
  130. displayrow(row)
  131. {
  132.     register RECORD *rec = DisplayTop;
  133.     register short i = row;
  134.  
  135.     while (i && rec) {
  136.     rec = rec->next;
  137.     while (rec && !(rec->flags & R_SELECTED))
  138.         rec = rec->next;
  139.     --i;
  140.     }
  141.     if (rec && row < Rows)
  142.     displayat(rec, row);
  143. }
  144.  
  145. displayat(rec, i)
  146. RECORD *rec;
  147. {
  148.     short len;
  149.  
  150.     len = strlen(rec->name);
  151.     if (len > Cols)
  152.     len = Cols;
  153.     if (rec == Highlighted) {
  154.     SetAPen(Rp, 0);
  155.     SetBPen(Rp, 1);
  156.     }
  157.     Move(Rp, Xs, Ys + (Rp->TxHeight*i) + Rp->TxBaseline);
  158.     Text(Rp, rec->name, len);
  159.     if (Cols > MaxNameLen && rec->comment) {
  160.     len = strlen(rec->comment);
  161.     if (len > Cols - MaxNameLen)
  162.         len = Cols - MaxNameLen;
  163.     Move(Rp, Xs + MaxNameLen * Rp->TxWidth, Ys + (Rp->TxHeight * i) + Rp->TxBaseline);
  164.     Text(Rp, rec->comment, len);
  165.     }
  166.     if (rec == Highlighted) {
  167.     SetAPen(Rp, 1);
  168.     SetBPen(Rp, 0);
  169.     }
  170. }
  171.  
  172. bigboxhit(y, up)
  173. {
  174.     RECORD *hl = Highlighted;
  175.     short row;
  176.  
  177.     Highlighted = NULL;
  178.     if (hl)
  179.     redisplayone(hl);
  180.     row = (y - Ys) / Rp->TxHeight;
  181.     if (row >= Rows || Rows < 0)
  182.     return(0);
  183.     for (hl = DisplayTop; hl && !(hl->flags & R_SELECTED); hl = hl->next);
  184.     while (hl && row) {
  185.     if (hl->flags & R_SELECTED)
  186.         --row;
  187.     hl = hl->next;
  188.     }
  189.     for (; hl && !(hl->flags & R_SELECTED); hl = hl->next);
  190.     if (Highlighted = hl) {
  191.     redisplayone(hl);
  192.     setcomment((hl->comment) ? hl->comment : "");
  193.     if (up)
  194.         activate_com();
  195.     }
  196. }
  197.  
  198. sliderhit()
  199. {
  200.     uword pos, fill;
  201.  
  202.     getsliderpos(&pos, &fill);
  203.     NewNumTop = pos * (NumSelected - Rows + 1) / 0xFFFF;
  204.     redisplay(1);
  205. }
  206.  
  207. /*
  208.  *  Add a disk volume to the list.  Determine
  209.  *  the root and add entries beginning at the
  210.  *  specification.
  211.  */
  212.  
  213. void
  214. add_volume(str)
  215. char *str;
  216. {
  217.     LOCK *lock;
  218.     char path[128];
  219.     int len;
  220.  
  221.     Highlighted = NULL;
  222.     Fib = malloc(sizeof(FIB));
  223.     if (Fib == NULL)
  224.     return;
  225.     resetsort();                /* also cleans up the database  */
  226.     path[0] = 0;
  227.     if (lock = Lock(str, ACCESS_READ)) {
  228.     if (Examine(lock, Fib)) {
  229.         buildpath(lock, path);
  230.         len = strlen(path);
  231.         if (path[len-1] == ':' || path[len-1] == '/') {
  232.         path[len] = '*';
  233.         path[len+1] = 0;
  234.         select_pattern(path, 1);
  235.         path[len] = 0;
  236.         }
  237.         Examine(lock, Fib);
  238.         if (Fib->fib_DirEntryType < 0) {
  239.         addentry(path, Fib->fib_Comment, Fib->fib_Size);
  240.         } else {
  241.         RECORD *base;
  242.  
  243.         /*  find start of killpatterns, if any    */
  244.         for (base = Rbase; base; base = base->next) {
  245.             if (strcmp(base->name, KILLNAME) < 0)
  246.             continue;
  247.             break;
  248.         }
  249.         title("Wait.. Scanning");
  250.         scandir(lock, path, base);
  251.         }
  252.         title("Wait.. Update");
  253.         rem_selected(NULL,   1);
  254.     }
  255.     UnLock(lock);
  256.     }
  257.     free(Fib);
  258.     strcat(path, "*");
  259.     title("Select path");
  260.     select_pattern(path, 0);
  261. }
  262.  
  263. buildpath(lock, path)
  264. LOCK *lock;
  265. char *path;
  266. {
  267.     LOCK *parent;
  268.     short plen, nlen;
  269.  
  270.     plen = strlen(path);
  271.     nlen = strlen(Fib->fib_FileName) + 1;
  272.     if (nlen == 1) {    /*  RAM: */
  273.     strcpy(Fib->fib_FileName, "ram");
  274.     nlen = 4;
  275.     }
  276.     bmov(path, path + nlen, plen + 1);
  277.     strcpy(path, Fib->fib_FileName);
  278.     if (Fib->fib_DirEntryType >= 0)
  279.     path[nlen-1] = '/';
  280.     if (parent = ParentDir(lock)) {
  281.     if (Examine(parent, Fib)) {
  282.         buildpath(parent, path);
  283.     }
  284.     UnLock(parent);
  285.     } else {
  286.     path[nlen-1] = ':';
  287.     }
  288. }
  289.  
  290. scandir(lock, path, base)
  291. LOCK *lock;
  292. char *path;
  293. RECORD *base;
  294. {
  295.     short restorelen = strlen(path);
  296.     short len = restorelen;
  297.     LOCK *olddirlock;
  298.  
  299.     if (path[restorelen-1] != ':' && path[restorelen-1] != '/') {
  300.     strcpy(path + restorelen, "/");
  301.     ++len;
  302.     }
  303.     olddirlock = CurrentDir(lock);
  304.     if (notkilled(path, base))
  305.     addentry(path, Fib->fib_Comment, Fib->fib_Size);
  306.     while (ExNext(lock, Fib)) {
  307.     strcpy(path+len, Fib->fib_FileName);
  308.     if (Fib->fib_DirEntryType < 0) {
  309.         if (notkilled(path, base))
  310.         addentry(path, Fib->fib_Comment, Fib->fib_Size);
  311.     } else {
  312.         LOCK *lock = Lock(Fib->fib_FileName, ACCESS_READ);
  313.         if (lock) {
  314.         FIB *oldfib = Fib;
  315.         if (Fib = malloc(sizeof(FIB))) {
  316.             Examine(lock, Fib);
  317.             scandir(lock, path, base);
  318.             UnLock(lock);
  319.             free(Fib);
  320.         }
  321.         Fib = oldfib;
  322.         }
  323.     }
  324.     }
  325.     CurrentDir(olddirlock);
  326.     path[restorelen] = 0;
  327. }
  328.  
  329. notkilled(path,base)
  330. char *path;
  331. RECORD *base;
  332. {
  333.     while (base && strcmp(base->name, KILLNAME) == 0) {
  334.     if (base->comment && newwildcmp(base->comment, path))
  335.         return(0);
  336.     base = base->next;
  337.     }
  338.     return(1);
  339. }
  340.  
  341. load_database(fi)
  342. FILE *fi;
  343. {
  344.     char name[132];
  345.     char comm[132];
  346.     char size[32];
  347.  
  348.     fgets(name, 128, fi);   /*  # entries per item  */
  349.     Highlighted = NULL;
  350.     resetsort();
  351.     title("Wait... Loading");
  352.     while (fgets(name, 128, fi) && fgets(comm, 128, fi) && fgets(size, 32, fi)) {
  353.     name[strlen(name)-1] = 0;   /*  remove newlines */
  354.     comm[strlen(comm)-1] = 0;
  355.     addentry(name, comm, atoi(size));
  356.     }
  357.     rem_selected(NULL, 1);
  358.     selectall();
  359.     redisplay(0);
  360. }
  361.  
  362. save_database(fi)
  363. FILE *fi;
  364. {
  365.     RECORD *rec;
  366.     char buf[32];
  367.  
  368.     cleanup();
  369.     title("Saving...");
  370.     fputs("3\n", fi);
  371.     for (rec = Rbase; rec; rec = rec->next) {
  372.     fwrite(rec->name, strlen(rec->name), 1, fi);
  373.     putc('\n', fi);
  374.     if (rec->comment)
  375.         fwrite(rec->comment, strlen(rec->comment), 1, fi);
  376.     putc('\n', fi);
  377.     sprintf(buf, "%ld\n", rec->bytes);
  378.     fputs(buf, fi);
  379.     if (ferror(fi))
  380.         break;
  381.     }
  382. }
  383.  
  384. selectall()
  385. {
  386.     RECORD *rec;
  387.     short len;
  388.  
  389.     Highlighted = NULL;
  390.     DisplayTop = NULL;
  391.     MaxNameLen = 0;
  392.     for (rec = Rbase; rec; rec = rec->next) {
  393.     if (rec->flags & R_KILLPAT)
  394.         continue;
  395.     len = strlen(rec->name);
  396.     if (MaxNameLen <= len)
  397.         MaxNameLen = len + 1;
  398.     rec->flags |= R_SELECTED;
  399.     }
  400.     NumSelected = NumEntries;
  401. }
  402.  
  403. select_pattern(str, noref)
  404. char *str;
  405. {
  406.     register RECORD *rec;
  407.     register short len;
  408.     short which = 0;
  409.  
  410.     if (*str == '+')    /*  ADD selected patterns   */
  411.     ++str, which = 1;
  412.     if (*str == '-')    /*  REMOVE selected patterns*/
  413.     ++str, which = 2;
  414.     DisplayTop = NULL;
  415.     Highlighted= NULL;
  416.  
  417.     switch(which) {
  418.     case 0:
  419.     NumSelected = 0;
  420.     MaxNameLen = 0;
  421.     for (rec = Rbase; rec; rec = rec->next) {
  422.         rec->flags &= ~R_SELECTED;
  423.         if (rec->flags & R_KILLPAT)
  424.         continue;
  425.         if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
  426.         if (noref) {
  427.             rec->flags |= R_UPDATE;
  428.         } else {
  429.             rec->flags |= R_SELECTED;
  430.             ++NumSelected;
  431.             if ((len = strlen(rec->name)) >= MaxNameLen)
  432.             MaxNameLen = len + 1;
  433.         }
  434.         }
  435.     }
  436.     break;
  437.     case 1:
  438.     for (rec = Rbase; rec; rec = rec->next) {
  439.         if ((rec->flags & R_KILLPAT) || (rec->flags & R_SELECTED))
  440.         continue;
  441.         if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
  442.         rec->flags |= R_SELECTED;
  443.         ++NumSelected;
  444.         if ((len = strlen(rec->name)) >= MaxNameLen)
  445.             MaxNameLen = len + 1;
  446.         }
  447.     }
  448.     break;
  449.     case 2:
  450.     for (rec = Rbase; rec; rec = rec->next) {
  451.         if (!(rec->flags & R_SELECTED))
  452.         continue;
  453.         if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
  454.         rec->flags &= ~R_SELECTED;
  455.         --NumSelected;
  456.         }
  457.     }
  458.     break;
  459.     }
  460.     if (!noref)
  461.     redisplay(0);
  462. }
  463.  
  464. /*
  465.  *  If onerec != NULL, remove the one record,
  466.  *  else remove all SELECTED records.
  467.  */
  468.  
  469. rem_selected(onerec, noref)
  470. RECORD *onerec;
  471. {
  472.     register RECORD *rec;
  473.     register long len, maxlen;
  474.  
  475.     Highlighted = NULL;
  476.     cleanup();
  477.     if (onerec) {
  478.     if (onerec->flags & R_SELECTED) {
  479.         onerec->flags &= ~R_SELECTED;
  480.         --NumSelected;
  481.     }
  482.     onerec->flags |= R_KILLPAT;
  483.     --NumEntries;
  484.     } else {
  485.     maxlen = 0;
  486.     for (rec = Rbase; rec; rec = rec->next) {
  487.         if (noref) {
  488.         if (rec->flags & R_UPDATE) {
  489.             rec->flags &= ~R_UPDATE;
  490.             rec->flags |= R_KILLPAT;
  491.             --NumEntries;
  492.         }
  493.         } else {
  494.         if (rec->flags & R_SELECTED) {
  495.             rec->flags &= ~R_SELECTED;
  496.             rec->flags |= R_KILLPAT;
  497.            --NumEntries;
  498.         }
  499.         }
  500.         if (!(rec->flags & R_KILLPAT) && (len=strlen(rec->name)) > maxlen)
  501.         maxlen = len;
  502.     }
  503.     if (!noref)
  504.         NumSelected = 0;
  505.     MaxNameLen = maxlen+1;
  506.     }
  507.     if (noref)
  508.     cleanup();
  509.     else
  510.     redisplay(0);
  511. }
  512.  
  513. undo()
  514. {
  515.     RECORD *rec;
  516.  
  517.     Highlighted = NULL;
  518.     for (rec = Rbase; rec; rec = rec->next) {
  519.     if (rec->flags & R_KILLPAT) {
  520.         rec->flags &= ~R_KILLPAT;
  521.         rec->flags |= R_SELECTED;
  522.         ++NumSelected;
  523.         ++NumEntries;
  524.         if (strlen(rec->name) >= MaxNameLen)
  525.         MaxNameLen = strlen(rec->name)+1;
  526.     }
  527.     }
  528.     redisplay(0);
  529. }
  530.  
  531. cleanup()
  532. {
  533.     RECORD *rec, *nrec;
  534.     for (rec = Rbase; rec; rec = nrec) {
  535.     nrec = rec->next;
  536.     if (rec->flags & R_KILLPAT) {
  537.         if (rec == DisplayTop)
  538.         DisplayTop = nrec;
  539.         rmrecord(rec);
  540.     }
  541.     }
  542. }
  543.  
  544. rmrecord(rec)
  545. RECORD *rec;
  546. {
  547.     if (rec->flags & R_SOFTERR) {
  548.     puts("panic: soft error");
  549.     exit(1);
  550.     }
  551.     if (rec->prev)
  552.     rec->prev->next = rec->next;
  553.     else
  554.     Rbase = rec->next;
  555.     if (rec->next)
  556.     rec->next->prev = rec->prev;
  557.     rec->flags |= R_SOFTERR;
  558.     freestr(rec->name);
  559.     freestr(rec->comment);
  560.     freerecord(rec);
  561. }
  562.  
  563. /*
  564.  *  modify the comment field for the highlighted
  565.  *  item.
  566.  */
  567.  
  568. mod_comment(str)
  569. char *str;
  570. {
  571.     if (Highlighted) {
  572.     Modified = 1;
  573.     freestr(Highlighted->comment);
  574.     if (str[0]) {
  575.         Highlighted->comment = allocstr(str);
  576.         if (Highlighted->comment == NULL)
  577.         title("OUT OF MEMORY!");
  578.     } else {
  579.         Highlighted->comment = NULL;
  580.     }
  581.     redisplayone(Highlighted);
  582.     }
  583. }
  584.  
  585. static RECORD *Cache;
  586.  
  587. resetsort()
  588. {
  589.     cleanup();
  590.     Cache = Rbase;
  591. }
  592.  
  593. void
  594. addentry(name, comm, size)
  595. char *name;
  596. char *comm;
  597. long size;
  598. {
  599.     RECORD *rec;
  600.     short n;
  601.  
  602.     Modified = 1;
  603.     rec = allocrecord();
  604.     if (rec == NULL) {
  605.     title("OUT OF MEMORY!");
  606.     return;
  607.     }
  608.     rec->name = allocstr(name);
  609.     if (rec->name == NULL) {
  610.     rmrecord(rec);
  611.     title("OUT OF MEMORY!");
  612.     return;
  613.     }
  614.     rec->comment = NULL;
  615.     if (strlen(comm)) {
  616.     rec->comment = allocstr(comm);
  617.     if (rec->comment == NULL) {
  618.         freestr(rec->name);
  619.         rmrecord(rec);
  620.         title("OUT OF MEMORY!");
  621.         return;
  622.     }
  623.     }
  624.     rec->bytes = size;
  625.  
  626.     if (Rbase == NULL) {
  627.     Rbase = rec;
  628.     rec->prev = NULL;
  629.     rec->next = NULL;
  630.     } else {
  631.     short n = strcmp(name, Cache->name);
  632.     if (n < 0) {                    /*  name < Cache, move backwards */
  633.         while ((Cache = Cache->prev) && (n=strcmp(name, Cache->name)) < 0);
  634.     } else
  635.     if (n > 0) {                    /*  name > Cache, move forwards  */
  636.         while (Cache->next && (n=strcmp(name, Cache->next->name)) > 0)
  637.         Cache = Cache->next;
  638.         if (Cache->next && n == 0)
  639.         Cache = Cache->next;
  640.     }
  641.     if (Cache) {
  642.         rec->next = Cache->next;    /*  insert after cache */
  643.         rec->prev = Cache;
  644.         Cache->next = rec;
  645.     } else {            /*  or at beginning    */
  646.         rec->next = Rbase;
  647.         rec->prev = NULL;
  648.         Rbase = rec;
  649.     }
  650.     if (rec->next)
  651.         rec->next->prev = rec;
  652.     if (n == 0) {                   /*  replace if exact   */
  653.         if (Cache->comment) {
  654.         char *swap = Cache->comment;
  655.         Cache->comment = rec->comment;
  656.         Cache->flags |= R_UPDATE;
  657.         rec->comment = swap;
  658.         }
  659.     }
  660.     }
  661.     rec->flags = R_SELECTED;
  662.     ++NumSelected;
  663.     ++NumEntries;
  664.     if (MaxNameLen <= strlen(rec->name))
  665.     MaxNameLen = strlen(rec->name) + 1;
  666.     Cache = rec;
  667. }
  668.  
  669.